<app-context-menu (itemClicked)="contextMenuItemClicked($event)"></app-context-menu>

<app-welcome-modal></app-welcome-modal>
<app-settings-modal (closed)="handleSettingsModalClosed()"></app-settings-modal>
<app-changelog-modal></app-changelog-modal>

<div class="toasts-container">
  <ngb-toast
    *ngFor="let toast of toasts$ | async"
    [class]="'toast-' + toast.type"
    [autohide]="true" [delay]="5000"
    (hide)="removeToast(toast.UUID)"
    (click)="removeToast(toast.UUID)"
  >
    {{toast.message}}
  </ngb-toast>
</div>

<div class="container-fluid h-100">
  <div class="d-flex flex-column h-100">
    <div class="row flex-fill mh0">
      <app-environments-menu class="environments-menu-container h-100"></app-environments-menu>

      <div class="col d-flex flex-column h-100">
        <!-- First row: env name +start / env port + prefix -->
        <div class="header">
          <div class="row">
            <ng-container *ngIf="activeEnvironment$ | async as activeEnvironment; else noActiveEnvironment"
              [formGroup]="activeEnvironmentForm">
              <div class="col-2 column-width">
                <div class="input-group">
                  <span *ngIf="activeEnvironmentState$ | async as activeEnvironmentState" class="input-group-prepend">
                    <button class="btn btn-link" type="button"
                      [ngClass]="{'text-success': !activeEnvironmentState.running && !activeEnvironmentState.needRestart, 'text-danger': activeEnvironmentState.running && !activeEnvironmentState.needRestart, 'text-warning': activeEnvironmentState.running && activeEnvironmentState.needRestart}"
                      (click)="toggleEnvironment()">
                      <i class="material-icons"
                        *ngIf="activeEnvironmentState.running && activeEnvironmentState.needRestart"
                        ngbTooltip="Server needs restart">refresh</i>
                      <i class="material-icons"
                        *ngIf="activeEnvironmentState.running && !activeEnvironmentState.needRestart"
                        ngbTooltip="Stop server">stop</i>
                      <i class="material-icons" *ngIf="!activeEnvironmentState.running"
                        ngbTooltip="Start server">play_arrow</i>
                    </button>
                  </span>
                  <input type="text" class="form-control" formControlName="name">
                </div>
              </div>

              <div class="col">
                <div class="input-group">
                  <div class="input-group-prepend">
                    <span class="input-group-text"><i class="material-icons"
                        ngbTooltip="Server available on all network interfaces (localhost, 127.0.0.1, etc)">power</i>
                      0.0.0.0 :</span>
                  </div>
                  <input type="text" class="form-control col-2" placeholder="port" formControlName="port"
                    [InputNumber]="{ min: 0, max: 65535 }" MousewheelUpdate>
                  <div class="input-group-prepend" *ngIf="duplicatedEnvironments$ | async as duplicatedEnvironments">
                    <span class="input-group-text text-warning"
                      *ngIf="duplicatedEnvironments?.has(activeEnvironment?.uuid)"
                      ngbTooltip="Port is shared with another environment"><i class="material-icons">warning</i></span>
                  </div>
                  <div class="input-group-prepend">
                    <span class="input-group-text">/</span>
                  </div>
                  <input type="text" class="form-control" placeholder="prefix" ValidPath
                    ngbTooltip="Environment routes prefix" formControlName="endpointPrefix">
                  <div class="input-group-prepend">
                    <span class="input-group-text"><i class="material-icons">access_time</i></span>
                  </div>
                  <input type="text" class="form-control col-2"
                    ngbTooltip="Global environment latency applied to all routes (ms)" formControlName="latency"
                    [InputNumber]="{ min: 0, max: Infinity }" MousewheelUpdate>
                </div>
              </div>

              <div class="col-2">
                <div class="btn btn-link btn-icon float-right"
                  [ngClass]="{'active': (activeView$ | async) === 'ENV_SETTINGS'}"
                  (click)="setActiveView('ENV_SETTINGS')" ngbTooltip="Environment settings">
                  <i class="material-icons">settings</i>
                </div>
                <div class="btn btn-link btn-icon float-right"
                  [ngClass]="{'active': (activeView$ | async) === 'ENV_LOGS'}" (click)="setActiveView('ENV_LOGS')"
                  ngbTooltip="Environment logs">
                  <i class="material-icons">history</i>
                </div>
              </div>

            </ng-container>

            <ng-template #noActiveEnvironment>
              <div class="col-2 column-width">
                <div class="input-group">
                  <span class="input-group-prepend">
                    <button class="btn btn-link text-muted" type="button">
                      <i class="material-icons">play_arrow</i>
                    </button>
                  </span>
                  <input type="text" class="form-control" placeholder="No environment" disabled>
                </div>
              </div>
            </ng-template>
          </div>
        </div>

        <div class="row flex-fill mh0">
          <app-routes-menu class="h-100"></app-routes-menu>

          <div *ngIf="activeEnvironment$ | async as activeEnvironment" class="col d-flex flex-column main-content h-100">

            <ng-container *ngIf="activeView$ | async as activeView">

              <!-- ENVIRONMENT SETTINGS AND LOGS VIEWS -->
              <ng-container *ngIf="activeView === 'ENV_SETTINGS' || activeView === 'ENV_LOGS'">
                <!-- title and back button -->
                <div class="row">
                  <div class="col">
                    <button *ngIf="activeRoute$ | async" type="button" class="btn btn-link btn-icon pl-2"
                      (click)="setActiveView('ROUTE')">
                      <i class="material-icons">arrow_back</i> Back
                    </button>
                    <button
                      *ngIf="(environmentsLogs$ | async)[activeEnvironment.uuid]?.length && activeView === 'ENV_LOGS'"
                      type="button" class="btn btn-link btn-icon pl-2 float-right" (click)="clearEnvironmentLogs()">
                      <span *ngIf="!(clearEnvironmentLogsRequested$ | async)"><i class="material-icons">delete</i>
                        Clear</span>
                      <span *ngIf="clearEnvironmentLogsRequested$ | async" class="text-danger"><i
                          class="material-icons">delete</i>
                        Confirm</span>
                    </button>
                  </div>
                </div>

                <!-- ENVIRONMENT SETTINGS VIEW -->
                <div *ngIf="activeView === 'ENV_SETTINGS'" class="d-flex flex-column h-100 m-2"
                  [formGroup]="activeEnvironmentForm">
                  <div class="row h-35">
                    <div class="col d-flex flex-column h-100">
                      <div class="title-separator is-first has-icon">
                        <div class="title-separator-icon text-primary"><i class="material-icons">security</i></div>
                        <div class="title-separator-text">
                          <div>Proxy mode</div>
                          <div>Non defined routes will be forwarded to the specified host<span
                              (click)="openWikiLink('proxy')" class="pl-2 btn btn-link text-primary cp doc-link"><i
                                class="material-icons">info</i></span></div>
                        </div>
                      </div>
                      <div class="form-inline pl-4">
                        <div class="custom-control custom-checkbox mr-4">
                          <input type="checkbox" class="custom-control-input" id="proxyMode"
                            formControlName="proxyMode">
                          <label class="custom-control-label" for="proxyMode">Enable</label>
                        </div>
                        <div class="input-group">
                          <input type="text" class="form-control" placeholder="URL" formControlName="proxyHost">
                          <div class="input-group-append">
                            <span class="input-group-text text-warning"
                              *ngIf="activeEnvironment.proxyMode && activeEnvironment.proxyHost && !isValidURL(activeEnvironment.proxyHost)"
                              ngbTooltip="The address must be a valid URL"><i class="material-icons">warning</i></span>
                          </div>
                        </div>
                      </div>
                      <!-- custom proxy headers -->
                      <ng-container *ngIf="activeEnvironment.proxyMode">
                        <div class="row pl-4">
                          <div class="col-6">
                            <div class="mt-2 mb-2">Proxy request headers <i
                              class="material-icons" ngbTooltip="Headers will be added to the request sent to the proxied server">info</i></div>
                          </div>
                          <div class="col-6">
                            <div class="mt-2 mb-2 pl-2">Proxy response headers <i
                              class="material-icons" ngbTooltip="Headers will be added to the response received from the proxied server">info</i></div>
                          </div>
                        </div>
                        <div class="row pl-4 h-100">
                          <div class="col-6 h-100 scroll-content" #environmentProxyReqHeadersContainer>
                            <app-headers-list [data$]="activeEnvironment$" headers="proxyReqHeaders" type="environmentHeaders"
                              (headerAdded)="scrollToBottom(environmentProxyReqHeadersContainer)"></app-headers-list>
                          </div>
                          <div class="col-6 h-100 pl-2 scroll-content" #environmentProxyResHeadersContainer>
                            <app-headers-list [data$]="activeEnvironment$" headers="proxyResHeaders" type="environmentHeaders"
                              (headerAdded)="scrollToBottom(environmentProxyResHeadersContainer)"></app-headers-list>
                          </div>
                        </div>
                      </ng-container>

                    </div>
                  </div>

                  <div class="row">
                    <div class="col">
                      <div class="title-separator has-icon">
                        <div class="title-separator-icon text-warning"><i class="material-icons">https</i></div>
                        <div class="title-separator-text">
                          <div>HTTPS </div>
                          <div><span (click)="openWikiLink('https')"
                              class="pl-2 btn btn-link text-primary cp doc-link"><i
                                class="material-icons">info</i></span></div>
                        </div>
                      </div>
                      <div class="form-inline pl-4">
                        <div class="custom-control custom-checkbox">
                          <input type="checkbox" class="custom-control-input" id="HTTPS" formControlName="https">
                          <label class="custom-control-label" for="HTTPS">Enable</label>
                        </div>
                      </div>
                    </div>
                  </div>

                  <div class="row">
                    <div class="col">
                      <div class="title-separator has-icon">
                        <div class="title-separator-icon text-info"><i class="material-icons">shuffle</i></div>
                        <div class="title-separator-text">
                          <div>CORS </div>
                          <div>Automatically handle OPTIONS requests<span (click)="openWikiLink('cors')"
                              class="pl-2 btn btn-link text-primary cp doc-link"><i
                                class="material-icons">info</i></span></div>
                        </div>
                      </div>
                      <div class="form-inline pl-4">
                        <div class="custom-control custom-checkbox">
                          <input type="checkbox" class="custom-control-input" id="CORS" formControlName="cors">
                          <label class="custom-control-label" for="CORS">Enable</label>
                        </div>
                        <button class="btn btn-link btn-icon text-primary form-right" type="button"
                          (click)="addCORSHeadersToEnvironment()">Add CORS headers to environment headers
                          below</button>
                      </div>
                    </div>
                  </div>

                  <div class="row flex-fill mh0">
                    <div class="col d-flex flex-column h-100">
                      <div class="title-separator has-icon">
                        <div class="title-separator-icon"><i class="material-icons text-purple">featured_play_list</i>
                        </div>
                        <div class="title-separator-text">
                          <div>Environment headers </div>
                          <div>Headers will be added to all routes of this environment<span
                              (click)="openWikiLink('headers')" class="pl-2 btn btn-link text-primary cp doc-link"><i
                                class="material-icons">info</i></span></div>
                        </div>
                      </div>

                      <div class="scroll-content flex-fill" #environmentHeadersContainer>
                        <app-headers-list [data$]="activeEnvironment$" type="environmentHeaders"
                          (headerAdded)="scrollToBottom(environmentHeadersContainer)"></app-headers-list>
                      </div>
                    </div>
                  </div>
                </div>

                <!-- ENVIRONMENT LOGS VIEW -->
                <div *ngIf="activeView === 'ENV_LOGS'" class="row flex-fill mh0">
                  <div class="col h-100">
                    <app-environment-logs [activeEnvironmentUUID$]="activeEnvironmentUUID$"
                      [environmentsLogs$]="environmentsLogs$"></app-environment-logs>
                  </div>
                </div>
              </ng-container>

              <!-- ROUTE VIEW -->
              <ng-container *ngIf="activeView === 'ROUTE'">
                <div class="p-2 h-100 d-flex flex-column overflow-hidden">
                  <ng-container *ngIf="activeRoute$ | async as activeRoute" [formGroup]="activeRouteForm">

                    <!-- Method + endpoint + warning + delete -->
                    <div class="row">
                      <div class="col">
                        <div class="input-group">
                          <select class="custom-select col-2" formControlName="method">
                            <option *ngFor="let method of methods" [value]="method"
                              [selected]="activeRouteForm.get('method').value === method">{{method | uppercase}}
                            </option>
                          </select>
                          <div class="input-group-prepend">
                            <span class="input-group-text">/</span>
                          </div>
                          <input type="text" class="form-control"
                            placeholder="Path supports regexes and params: */:var/a(b)?c/[0-9]{1,5}" ValidPath
                            formControlName="endpoint">
                          <div class="input-group-prepend">
                            <span
                              *ngIf="(environmentsStatus$ | async)[activeEnvironment.uuid].running && activeRoute.method === 'get'"
                              class="input-group-text text-primary" ngbTooltip="Open route in browser"
                              (click)="openRouteInBrowser()"><i class="material-icons">open_in_new</i></span>
                          </div>
                          <div class="input-group-prepend">
                            <span *ngIf="routeHasQueryParams()" class="input-group-text text-warning"
                              ngbTooltip="Route cannot be declared with query parameters, please add them when you call the route"><i
                                class="material-icons">warning</i></span>
                          </div>
                        </div>
                      </div>
                    </div>

                    <!-- Documentation -->
                    <div class="row mt-2">
                      <div class="col">
                        <div class="input-group">
                          <input type="text" class="form-control" placeholder="Add notes or documentation" ValidPath
                            formControlName="documentation">
                        </div>
                      </div>
                    </div>

                    <!-- Navigation tabs -->
                    <ng-container *ngIf="activeTab$ | async as activeTab">
                      <div class="row mt-4" id="route-responses-menu">
                        <div class="col d-flex flex-row align-items-center">
                          <!-- Responses dropdown -->
                          <div *ngIf="activeRouteResponse$ | async as activeRouteResponse" class="btn-group dropdown mr-1" ngbDropdown>
                            <button type="button" class="btn btn-custom" (click)="addRouteResponse()">
                              <i class="material-icons">add</i> <span class="d-none d-xl-inline">Add response</span>
                            </button>
                            <button type="button" class="btn btn-custom dropdown-toggle dropdown-toggle-split mr-1"
                              role="button" id="route-responses-dropdown" aria-haspopup="true" aria-expanded="false"
                              ngbDropdownToggle>
                                <div class="route-responses-dropdown-content">
                                  <span class="pr-2">{{activeRouteResponseIndex$ | async}}: {{activeRouteResponse?.statusCode}}</span> {{activeRouteResponse?.label}}</div>
                            </button>

                            <div class="dropdown-menu" aria-labelledby="route-responses-dropdown" ngbDropdownMenu MousedragDeadzone dragula="routeResponses"
                            [dragulaModel]="activeRoute.responses">
                              <button type="button" *ngFor="let routeResponse of activeRoute.responses; index as routeResponseIndex"
                                class="btn dropdown-item d-flex"
                                [ngClass]="{'active': activeRouteResponse?.uuid === routeResponse.uuid}"
                                ngbDropdownItem
                                (click)="setActiveRouteResponse(routeResponse.uuid)">
                                <span class="flex-grow-1 mr-2">{{routeResponseIndex + 1}}: {{routeResponse.statusCode}} {{routeResponse.label | truncate: 20}}</span>
                                <span><i *ngIf="routeResponseIndex === 0" class="material-icons text-primary" ngbTooltip="Default response served if no rule matches">flag</i></span>
                              </button>
                            </div>
                          </div>

                          <!-- Response settings -->
                          <ul class="nav nav-tabs flex-grow-1">
                            <li class="nav-item">
                              <a class="nav-link" [ngClass]="{'active': activeTab === 'RESPONSE'}"
                              (click)="setActiveTab('RESPONSE')">Status & Body</a>
                            </li>
                            <li class="nav-item">
                              <a class="nav-link" [ngClass]="{'active': activeTab === 'HEADERS'}"
                              (click)="setActiveTab('HEADERS')">Headers <i *ngIf="hasEnvironmentHeaders()"
                              class="material-icons text-purple"
                              ngbTooltip="Some environment headers are defined">featured_play_list</i></a>
                            </li>
                            <li class="nav-item">
                              <a class="nav-link" [ngClass]="{'active': activeTab === 'RULES'}"
                                (click)="setActiveTab('RULES')">Rules <span
                                (click)="openWikiLink('rules')"
                                class="btn btn-link text-primary cp doc-link ml-2"><i
                                  class="material-icons">info</i></span></a>
                            </li>
                          </ul>

                          <!-- Response delete button -->
                          <button *ngIf="activeRoute?.responses.length > 1" type="button" class="btn btn-link btn-icon"
                            (click)="deleteCurrentRouteResponse()">
                            <span *ngIf="!(deleteCurrentRouteResponseRequested$ | async)" ngbTooltip="Delete response"><i
                                class="material-icons">delete</i></span>
                            <span *ngIf="deleteCurrentRouteResponseRequested$ | async" class="text-danger" ngbTooltip="Confirm deletion"><i
                                class="material-icons">delete</i></span>
                          </button>
                        </div>
                      </div>
                    </ng-container>
                  </ng-container>

                  <ng-container *ngIf="activeRouteResponse$ | async as activeRouteResponse">

                    <!-- RESPONSE & BODY tab -->
                    <ng-container *ngIf="(activeTab$ | async) === 'RESPONSE'" [formGroup]="activeRouteResponseForm">
                      <!-- status code + latency -->
                      <div class="row mt-3">
                        <!-- route status code -->
                        <div class="col">
                          <div class="input-group">
                            <select class="custom-select col-4" formControlName="statusCode">
                              <option *ngFor="let statusCode of statusCodes" [value]="statusCode.code"
                                [selected]="activeRouteResponse.statusCode === statusCode.code">{{statusCode.code}}
                                -
                                {{statusCode.text}}</option>
                            </select>
                            <div class="input-group-prepend">
                              <span class="input-group-text"><i class="material-icons">access_time</i></span>
                            </div>
                            <input type="text" class="form-control col-1" ngbTooltip="Route specific latency (ms)"
                              [InputNumber]="{min: 0, max: Infinity}" MousewheelUpdate formControlName="latency">
                            <input type="text" class="form-control ml-1" formControlName="label" placeholder="Add label or notes">
                          </div>
                        </div>
                      </div>

                      <div class="row">
                        <div class="col">
                          <div class="title-separator has-icon">
                            <div class="title-separator-icon text-secondary"><i
                                class="material-icons">insert_drive_file</i></div>
                            <div class="title-separator-text">
                              <div>File </div>
                              <div>Selecting a file will automatically serve its content with the detected
                                Content-Type
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>

                      <!-- body: file -->
                      <div class="row">
                        <div class="col">
                          <div class="form-inline">
                            <div class="input-group col-9">
                              <div class="input-group-prepend">
                                <button class="btn btn-link" (click)="browseFiles()"><i
                                    class="material-icons">find_in_page</i></button>
                              </div>
                              <input type="text" class="form-control" formControlName="filePath">
                              <div class="input-group-prepend">
                                <span *ngIf="activeRouteResponse.filePath" class="input-group-text text-danger"
                                  (click)="activeRouteResponseForm.get('filePath').setValue('')"
                                  ngbTooltip="Remove file serving">
                                  <i class="material-icons">delete</i>
                                </span>
                              </div>
                            </div>
                            <div class="form-group col-3">
                              <div *ngIf="activeRouteResponse.filePath" class="custom-control custom-checkbox">
                                <input type="checkbox" class="custom-control-input" id="sendFileAsBody"
                                  formControlName="sendFileAsBody">
                                <label class="custom-control-label" for="sendFileAsBody">Send as body</label>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                      <div class="row">
                        <div class="col">
                          <div>
                            &nbsp;<small *ngIf="activeRouteResponse.filePath" class="text-muted">Detected MIME type:
                              {{getFileMimeType(activeRouteResponse.filePath).mimeType || 'none'}} <span
                                *ngIf="getFileMimeType(activeRouteResponse.filePath).supportsTemplating"> - Supports
                                templating
                                <span (click)="openWikiLink('templating')"
                                  class="pl-2 btn btn-link text-primary cp doc-link"><i
                                    class="material-icons">info</i></span></span></small>
                          </div>
                        </div>
                      </div>

                      <!-- body: custom content -->
                      <div class="row transition flex-fill" [ngClass]="{'dimmed': activeRouteResponse.filePath}">
                        <div class="col d-flex flex-column">
                          <div class="title-separator has-icon">
                            <div class="title-separator-icon text-secondary">
                              <span class="clickable" (click)="formatBody()" ngbTooltip="Format body"><i class="material-icons">subject</i></span>
                            </div>
                            <div class="title-separator-text">
                              <div>Body </div>
                              <div *ngIf="activeRouteResponse.filePath" class="text-warning">A file is selected, this
                                body will not be served</div>
                              <div *ngIf="!activeRouteResponse.filePath">{{getRouteResponseContentType()}} <span
                                  (click)="openWikiLink('templating')"
                                  class="btn btn-link text-primary cp doc-link"><i
                                    class="material-icons">info</i></span></div>
                            </div>
                          </div>
                          <div class="flex-fill" *ngIf="bodyEditorConfig$ | async as bodyEditorConfig">
                            <ace-editor class="h-100" [options]="bodyEditorConfig?.options"
                              [mode]="bodyEditorConfig?.mode" [theme]="bodyEditorConfig?.theme"
                              [text]="activeRouteResponseForm.get('body').value"
                              (textChanged)="activeRouteResponseForm.get('body').setValue($event)"></ace-editor>
                          </div>
                        </div>
                      </div>
                    </ng-container>

                    <!-- HEADERS tab -->
                    <ng-container *ngIf="(activeTab$ | async) === 'HEADERS'">
                      <div class="row">
                        <div class="col">
                          <button class="btn btn-link btn-icon text-primary mb-2" type="button"
                            (click)="setActiveView('ENV_SETTINGS')">Go to environment headers</button>
                        </div>
                      </div>

                      <div class="row flex-fill mh0">
                        <div class="col scroll-content h-100" #routeHeadersContainer>
                          <app-headers-list [data$]="activeRouteResponse$" type="routeResponseHeaders"
                            (headerAdded)="scrollToBottom(routeHeadersContainer)"></app-headers-list>
                        </div>
                      </div>
                    </ng-container>

                    <!-- RULES tab -->
                    <ng-container *ngIf="(activeTab$ | async) === 'RULES'">
                      <div class="row flex-fill mh0">
                        <div class="col scroll-content h-100" #routeResponseRulesContainer>
                          <app-route-response-rules [data$]="activeRouteResponse$" (ruleAdded)="scrollToBottom(routeResponseRulesContainer)"></app-route-response-rules>
                        </div>
                      </div>
                    </ng-container>
                  </ng-container>
                </div>
              </ng-container>
            </ng-container>

          </div>

        </div>

      </div>
    </div>

    <div class="footer">
      <div class="row">
        <div class="col pl-0 pr-0">
          <div class="footer-item with-border-right" (click)="openChangelogModal()" ngbTooltip="View changelog">
            v{{appVersion}}</div>
          <div class="footer-item with-border-right" *ngIf="updateAvailable">
            <button class="btn btn-xs btn-success" (click)="applyUpdate()"><i
                class="material-icons material-icons-xs">update</i> New version available, click to
              {{(platform === 'win32') ? 'apply' : 'download'}}</button>
          </div>
          <div class="footer-item with-border-right">
            <app-banner></app-banner>
          </div>
          <div class="footer-item float-right with-border-left" (click)="openFeedbackLink()"><i
              class="material-icons">feedback</i> Send feedback</div>
        </div>
      </div>
    </div>
  </div>
</div>
